#include "ImaMqInterface.h"
#include "ImaGlobals.h"
#include "ImaConstants.h"
#include <string.h>
#include <sys/types.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <errno.h>

ImaMqInterface* ImaMqInterface::mpMqInterface = NULL;

ImaMqInterface* ImaMqInterface::getInstance(ImaConf& conf) {
	if(mpMqInterface == NULL) {
		LOG(debug, __FILE__, __LINE__, "creating Posix Message Queue interface object");
		mpMqInterface = new ImaMqInterface(conf);
	}
	return mpMqInterface;
}

ImaMqInterface::ImaMqInterface(ImaConf& conf): mRegConfCodeMsgQId(0), mNewPasswordMsgQId(0) {
	LOG(debug, __FILE__, __LINE__, "ImaMqInterface::ImaMqInterface() called");

	if((mRegConfCodeMsgQId = msgget(conf.mSysVRegConfCodeMsgQKey, 0644)) == -1) {//TODO: replace this line with above one in future
		char log_msg[1024];
		sprintf(log_msg, "Failed to connect to message queue with key: %d", conf.mSysVRegConfCodeMsgQKey);
        LOG(error, __FILE__, __LINE__, log_msg);
        exit(1);
    } else {
		char log_msg[1024];
		sprintf(log_msg, "connected to message queue with key %d", conf.mSysVRegConfCodeMsgQKey);
		LOG(info, __FILE__, __LINE__, log_msg);
	}

	if((mNewPasswordMsgQId = msgget(conf.mSysVNewPasswordQKey, 0644 | IPC_CREAT)) == -1) {//TODO: replace this line with above one in future
		char log_msg[1024];
		sprintf(log_msg, "Failed to connect to message queue with key: %d", conf.mSysVNewPasswordQKey);
        LOG(error, __FILE__, __LINE__, log_msg);
        exit(1);
    } else {
		char log_msg[1024];
		sprintf(log_msg, "Connected to message queue with key %d", conf.mSysVNewPasswordQKey);
		LOG(info, __FILE__, __LINE__, log_msg);
	}

	if((mUserFeedbackMsgQId = msgget(conf.mSysVUserFeedbackQKey, 0644 | IPC_CREAT)) == -1) {//TODO: replace this line with above one in future
		char log_msg[1024];
		sprintf(log_msg, "Failed to connect to message queue with key: %d", conf.mSysVUserFeedbackQKey);
        LOG(error, __FILE__, __LINE__, log_msg);
        exit(1);
    } else {
		char log_msg[1024];
		sprintf(log_msg, "Connected to message queue with key %d", conf.mSysVUserFeedbackQKey);
		LOG(info, __FILE__, __LINE__, log_msg);
	}
}

ImaMqInterface::~ImaMqInterface() {
	LOG(debug, __FILE__, __LINE__, "ImaMqInterface::~ImaMqInterface() called");
}

bool ImaMqInterface::deqeueConfCode(char* pBuf) {
	LOG(debug, __FILE__, __LINE__, "ImaMqInterface::deqeueConfCode called");
	return dequeueMessage(mRegConfCodeMsgQId, pBuf);
}

bool ImaMqInterface::deqeueNewPassword(char* pBuf) {
	LOG(debug, __FILE__, __LINE__, "ImaMqInterface::deqeueNewPassword called");
	return dequeueMessage(mNewPasswordMsgQId, pBuf);
}

bool ImaMqInterface::dequeueFeedbackMsg(char* pBuf) {
	LOG(debug, __FILE__, __LINE__, "ImaMqInterface::dequeueFeedbackMsg called");
	return dequeueMessage(mUserFeedbackMsgQId, pBuf);
}

bool ImaMqInterface::dequeueMessage(int msgQId, char* pBuf) {
	LOG(debug, __FILE__, __LINE__, "ImaMqInterface::dequeueMessage called");
	msgbuf rbuf;

	if (msgrcv(msgQId, &rbuf, MSGQBUFSZ, 0, IPC_NOWAIT) < 0) {
		if(errno == ENOMSG) {
			LOG(debug, __FILE__, __LINE__, "No messages in the message queue");
			return false;
		} else {
			char log_msg[1024];
			sprintf(log_msg, "msgrcv error: %s", strerror(errno));
			LOG(error, __FILE__, __LINE__, log_msg);
			return false;
		}
	}

	strcpy(pBuf, rbuf.msg_buf);

	char log_msg[1024];
	sprintf(log_msg, "Returning dequeued message: %s", pBuf);
	LOG(debug, __FILE__, __LINE__, log_msg);

	return true;
}
